package topic

import (
	"community-service/cmd/api/internal/models/model"
	"community-service/cmd/api/internal/svc"
	"community-service/cmd/api/internal/types"
	e "community-service/pkg/errorx"
	"context"
	"fmt"
	user "gitee.com/vzerx/proto-contracts/auth"
	"github.com/zeromicro/go-zero/core/logx"
	"google.golang.org/grpc/codes"
)

type UserListTopicPostLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewUserListTopicPostLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserListTopicPostLogic {
	return &UserListTopicPostLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *UserListTopicPostLogic) UserListTopicPost(req *types.UserPostReq) (*types.UserPostList, error) {
	var resp types.UserPostList
	query := l.svcCtx.DB.WithContext(l.ctx).Model(&model.CsCommunityPost{}).
		Joins("post").
		Joins(fmt.Sprintf("INNER JOIN %s topic ON post.topic_id = topic.id", model.TableNameCsCommunityTopic)).
		Where("status = ?", types.PostTypeShelved).
		Group("post.id")

	if req.TopicId != 0 {
		// 检查话题是否存在
		var topic model.CsCommunityTopic
		if err := l.svcCtx.DB.WithContext(l.ctx).Model(&model.CsCommunityTopic{}).
			Where("id = ?", req.TopicId).Find(&topic).Error; err != nil {
			return nil, e.NewGrpcErr(codes.Internal, e.DBError)
		}
		if topic.ID == 0 {
			return nil, e.NewGrpcErr(codes.NotFound, e.TopicNotFound)
		}
		query.Where("post.topic_id = ?", req.TopicId)
	}

	if req.MenuId != 0 {
		var menu model.CsCommunityMenu
		if err := l.svcCtx.DB.WithContext(l.ctx).Model(&model.CsCommunityMenu{}).
			Where("id = ?", req.MenuId).Find(&menu).Error; err != nil {
			return nil, e.NewGrpcErr(codes.Internal, e.DBError)
		}
		if menu.ID == 0 || !menu.Publish {
			return nil, e.NewGrpcErr(codes.NotFound, e.MenuNotFound)
		}
		query.Where("topic.menu_id = ?", req.MenuId)
	}

	// 按名称模糊搜索
	if req.Name != "" {
		query.Where("title LIKE ? OR post.content LIKE ?", "%"+req.Name+"%", "%"+req.Name+"%")
	}

	if req.Self {
		query.Where("post.create_user = ?", req.UserProfile.UserId)
	}

	// 查询对应实验的帖子
	if req.ExperimentId != 0 {
		query.Joins(fmt.Sprintf("INNER JOIN %s exp ON exp.post_id = post.id", model.TableNameCsCommunityPostExperimentMap))
		query.Where("exp.experiment_id = ?", req.ExperimentId)
	} else {
		query.Joins(fmt.Sprintf("LEFT JOIN %s exp ON exp.post_id = post.id", model.TableNameCsCommunityPostExperimentMap))
	}

	// 查询总数
	if err := query.Count(&resp.Total).Error; err != nil {
		return nil, e.NewGrpcErr(codes.Internal, e.DBError)
	}

	// 查询帖子列表，包含点赞统计和实验信息
	query.Joins(fmt.Sprintf("LEFT JOIN %s approve ON approve.post_id = post.id", model.TableNameCsCommunityPostApprove)).
		Joins(fmt.Sprintf("LEFT JOIN %s comment ON comment.post_id = post.id", model.TableNameCsCommunityPostComment))

	query.Select(
		"post.id", "post.topic_id", "post.title", "post.status",
		"topic.name topic_name",
		// "post.content", // List不查询
		"post.is_topped", "post.is_selected", "post.is_official",
		"post.view_count", "post.reason", "post.create_user", "post.create_username",
		"IFNULL(COUNT(DISTINCT approve.id), 0) as approve_count",
		fmt.Sprintf("CASE WHEN post.create_user = %d THEN 1 ELSE 0 END as owner", req.UserProfile.UserId),
		"IFNULL(COUNT(DISTINCT comment.id), 0) as comment_count",
		"UNIX_TIMESTAMP(post.created_at) as created_at",
		"UNIX_TIMESTAMP(post.updated_at) as updated_at",
		"IFNULL(exp.experiment_id, 0) as experiment_id",
		"IFNULL(exp.experiment_name, '') as experiment_name",
		"IFNULL(exp.course_resource_id, '') as course_resource_id",
	)

	// 查询最火10个内容
	if req.Hot {
		query.Order("post.view_count DESC").Limit(10)
	} else {
		query.Order("post.is_topped DESC, post.is_selected DESC, post.is_official DESC, post.created_at DESC").
			Limit(req.PageSize).Offset((req.PageNum - 1) * req.PageSize)
	}

	// 临时结构体接收查询结果
	type PostWithExperiment struct {
		Id               int64  `json:"id"`
		TopicId          int64  `json:"topic_id"`
		TopicName        string `json:"topic_name"`
		Title            string `json:"title"`
		Content          string `json:"content"`
		Status           int32  `json:"status"`
		IsTopped         bool   `json:"is_topped"`
		IsSelected       bool   `json:"is_selected"`
		IsOfficial       bool   `json:"is_official"`
		ViewCount        int64  `json:"view_count"`
		Owner            bool   `json:"owner"`
		Reason           string `json:"reason"`
		CreateUser       int64  `json:"create_user"`
		CreateUsername   string `json:"create_username"`
		ApproveCount     int64  `json:"approve_count"`
		CommentCount     int64  `json:"comment_count"`
		CreatedAt        int64  `json:"created_at"`
		UpdatedAt        int64  `json:"updated_at"`
		ExperimentId     int64  `json:"experiment_id"`
		ExperimentName   string `json:"experiment_name"`
		CourseResourceId string `json:"course_resource_id"`
	}

	var rawPosts []PostWithExperiment
	if err := query.Find(&rawPosts).Error; err != nil {
		return nil, e.NewGrpcErr(codes.Internal, e.DBError)
	}

	for _, raw := range rawPosts {
		post := &types.UserPostRsp{
			PostRsp: types.PostRsp{
				Id:      raw.Id,
				Title:   raw.Title,
				Content: raw.Content,
				Status:  raw.Status,
				Reason:  raw.Reason,
				Topic: &types.TopicRsp{
					Id:   raw.TopicId,
					Name: raw.TopicName,
				},
				IsTopped:       raw.IsTopped,
				IsSelected:     raw.IsSelected,
				IsOfficial:     raw.IsOfficial,
				Owner:          raw.Owner,
				CreateUser:     raw.CreateUser,
				CreateUsername: raw.CreateUsername,
				CreatedAt:      raw.CreatedAt,
				UpdatedAt:      raw.UpdatedAt,
				Author: &types.AuthorRsp{
					Id:     raw.CreateUser,
					Name:   raw.CreateUsername,
					Avatar: "",
				},
				ApproveCount: raw.ApproveCount,
				ViewCount:    raw.ViewCount,
				CommentCount: raw.CommentCount,
				Experiment:   nil,
			},
		}

		if raw.ExperimentId != 0 {
			post.Experiment = &types.Experiment{
				Id:               raw.ExperimentId,
				Name:             raw.ExperimentName,
				CourseResourceId: raw.CourseResourceId,
			}
		}

		userInfo, err := l.svcCtx.User.GetUserInfo(l.ctx, &user.UserInfoReq{UserId: raw.CreateUser})
		if err == nil {
			post.Author = &types.AuthorRsp{
				Id:            userInfo.UserId,
				Name:          userInfo.UserName,
				Sex:           userInfo.Sex,
				Avatar:        userInfo.Avatar,
				CollageName:   userInfo.CollageName,
				SecondOrgName: userInfo.SecOrgName,
				OrgName:       userInfo.OrgName,
			}
		}

		// 查询最后一个回复的用户
		var lastComment model.CsCommunityPostComment

		if err := l.svcCtx.DB.WithContext(l.ctx).Model(&lastComment).
			Where("post_id = ?", raw.Id).
			Order("created_at DESC").
			Limit(1).
			Find(&lastComment).Error; err != nil {
			return nil, e.NewGrpcErr(codes.Internal, e.DBError)
		}
		// 如果有最后回复人
		if lastComment.ID != 0 {
			post.LatestAnswerUser = &types.AuthorRsp{
				Id:     lastComment.CreateUser,
				Name:   lastComment.CreateUsername,
				Avatar: "",
			}

			// 查询详细信息
			userInfo, err = l.svcCtx.User.GetUserInfo(l.ctx, &user.UserInfoReq{
				UserId: lastComment.CreateUser,
			})
			if err == nil {
				post.LatestAnswerUser = &types.AuthorRsp{
					Id:            userInfo.UserId,
					Name:          userInfo.UserName,
					Sex:           userInfo.Sex,
					Avatar:        userInfo.Avatar,
					CollageName:   userInfo.CollageName,
					SecondOrgName: userInfo.SecOrgName,
					OrgName:       userInfo.OrgName,
				}
			}
		}
		resp.Data = append(resp.Data, post)
	}

	return &resp, nil
}
